import type { ColEx } from "../types";
import type { FormProps, FormSchemaInner as FormSchema, AdvanceState } from "../types/form";
import { isBoolean, isFunction, isNumber, isObject } from "@/utils/is";
import { useBreakpoint } from "@/hooks/event/useBreakpoint";
import { useEffect, useMemo, useRef } from "react";
import { debounce } from "@/utils/index";

const BASIC_COL_LEN = 24;

interface UseAdvancedContext {
	advanceState: AdvanceState;
	getProps: FormProps;
	getSchema: FormSchema[];
	defaultValueRef: Recordable;
	setAdvanceState: any;
	advancedChange?: Function;
}

export default function ({
	advanceState,
	getProps,
	getSchema,
	defaultValueRef,
	setAdvanceState,
	advancedChange
}: UseAdvancedContext) {
	const { realWidthRef, screenEnum, screenRef } = useBreakpoint();

	const getEmptySpan = useMemo((): number => {
		if (!advanceState.isAdvanced) return 0;

		// For some special cases, you need to manually specify additional blank lines
		const emptySpan = getProps.emptySpan || 0;

		if (isNumber(emptySpan)) return emptySpan;

		if (isObject(emptySpan)) {
			const { span = 0 } = emptySpan;
			const screen = screenRef as string;

			const screenSpan = (emptySpan as any)[screen.toLowerCase()];
			return screenSpan || span || 0;
		}
		return 0;
	}, [advanceState.isAdvanced, getProps.emptySpan]);

	const debounceUpdateAdvanced = debounce(updateAdvanced, 30);

	function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) {
		const width = realWidthRef;

		const mdWidth =
			Number.parseInt(itemCol.md as string) ||
			Number.parseInt(itemCol.xs as string) ||
			Number.parseInt(itemCol.sm as string) ||
			(itemCol.span as number) ||
			BASIC_COL_LEN;

		const lgWidth = Number.parseInt(itemCol.lg as string) || mdWidth;
		const xlWidth = Number.parseInt(itemCol.xl as string) || lgWidth;
		const xxlWidth = Number.parseInt(itemCol.xxl as string) || xlWidth;
		if (width <= screenEnum.LG) itemColSum += mdWidth;
		else if (width < screenEnum.XL) itemColSum += lgWidth;
		else if (width < screenEnum.XXL) itemColSum += xlWidth;
		else itemColSum += xxlWidth;

		let advanceStateRef = advanceState;
		if (isLastAction) {
			advanceStateRef.hideAdvanceBtn = false;
			setAdvanceState({
				...advanceState,
				hideAdvanceBtn: false
			});
			if (itemColSum <= BASIC_COL_LEN * 2) {
				// When less than or equal to 2 lines, the collapse and expand buttons are not displayed
				advanceStateRef.hideAdvanceBtn = true;
				advanceStateRef.isAdvanced = true;
				setAdvanceState({
					...advanceState,
					hideAdvanceBtn: true,
					isAdvanced: true
				});
			} else if (itemColSum > BASIC_COL_LEN * 2 && itemColSum <= BASIC_COL_LEN * (getProps.autoAdvancedLine || 3)) {
				// More than 3 lines collapsed by default
				advanceStateRef.hideAdvanceBtn = false;
				setAdvanceState({
					...advanceState,
					hideAdvanceBtn: false
				});
			} else if (!advanceState.isLoad) {
				advanceStateRef.isLoad = true;
				advanceStateRef.isAdvanced = !advanceState.isAdvanced;
				setAdvanceState({
					...advanceState,
					isLoad: true,
					isAdvanced: !advanceState.isAdvanced
				});
			}
			return { isAdvanced: advanceStateRef.isAdvanced, itemColSum };
		}
		if (itemColSum > BASIC_COL_LEN * (getProps.alwaysShowLines || 1)) {
			return { isAdvanced: advanceStateRef.isAdvanced, itemColSum };
		} else {
			// The first line is always displayed
			return { isAdvanced: true, itemColSum };
		}
	}

	const fieldsIsAdvancedMap = useRef<Recordable<any>>({});

	function updateAdvanced() {
		let itemColSum = 0;
		let realItemColSum = 0;
		const { baseColProps = {} } = getProps;

		for (const schema of getSchema) {
			const { show, colProps } = schema;
			let isShow = true;

			if (isBoolean(show)) isShow = show;

			if (isFunction(show)) {
				isShow = show({
					schema,
					field: schema.field,
					values: {
						...defaultValueRef
					}
				});
			}

			if (isShow && (colProps || baseColProps)) {
				const { itemColSum: sum, isAdvanced } = getAdvanced({ ...baseColProps, ...colProps }, itemColSum);

				itemColSum = sum || 0;
				if (isAdvanced) realItemColSum = itemColSum;

				fieldsIsAdvancedMap.current[schema.field] = isAdvanced;
			}
		}

		setAdvanceState({
			...advanceState,
			actionSpan: (realItemColSum % BASIC_COL_LEN) + getEmptySpan
		});

		getAdvanced(getProps.actionColOptions || { span: BASIC_COL_LEN }, itemColSum, true);

		// to notify parent component "Table" change height.
		advancedChange && advancedChange();
	}

	function handleToggleAdvanced() {
		setAdvanceState({
			...advanceState,
			isAdvanced: !advanceState.isAdvanced
		});
	}

	useEffect(() => {
		const { showAdvancedButton } = getProps;
		if (showAdvancedButton) debounceUpdateAdvanced();
	}, [getSchema, advanceState.isAdvanced, realWidthRef]);

	return { handleToggleAdvanced, fieldsIsAdvancedMap: fieldsIsAdvancedMap.current };
}
